#include "klippy/config.h"
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "nlohmann/json.hpp"
#include <unordered_map>
#include <regex>

using namespace klippy;

std::shared_ptr<Config> Config::load(const std::string& filename) {
    // 使用new创建实例，然后构造shared_ptr
    Config* raw_ptr = new Config();
    std::shared_ptr<Config> config(raw_ptr);
    
    // 加载默认验证规则
    config->load_default_validation_rules();
    
    if (!config->parse_file(filename)) {
        throw std::runtime_error("Failed to load config file: " + filename);
    }
    return config;
}

bool Config::parse_file(const std::string& filename) {
    std::unordered_map<std::string, std::string> config_map;
    
    // 尝试作为JSON文件解析
    try {
        std::ifstream file(filename);
        nlohmann::json j;
        file >> j;
        
        if (j.is_object()) {
            config_ = j;
            config_path_ = filename;
            logger_.log(Logger::INFO, "Loaded JSON config file: " + filename);
            return validate();
        }
    } catch (...) {
        // 不是JSON文件，继续尝试键值对格式
    }

    // 传统键值对格式解析
    std::ifstream file(filename);
    if (!file.is_open()) {
        logger_.log(Logger::ERROR, "Cannot open config file: " + filename);
        return false;
    }

    std::string line;
    while (std::getline(file, line)) {
        // Skip comments and empty lines
        if (line.empty() || line[0] == '#') continue;

        size_t pos = line.find('=');
        if (pos == std::string::npos) continue;

        std::string key = line.substr(0, pos);
        std::string value = line.substr(pos + 1);
        
        // Trim whitespace
        key.erase(0, key.find_first_not_of(" \t"));
        key.erase(key.find_last_not_of(" \t") + 1);
        value.erase(0, value.find_first_not_of(" \t"));
        value.erase(value.find_last_not_of(" \t") + 1);

        config_map[key] = value;
    }

    // 将键值对转换为JSON格式
    if (!config_map.empty()) {
        config_ = nlohmann::json::object();
        for (const auto& [key, value] : config_map) {
            config_[key] = value;
        }
    }

    config_path_ = filename;
    logger_.log(Logger::INFO, "Loaded config file: " + filename);
    return validate();
}

void Config::add_validation_rule(const std::string& key, const ConfigValidationRule& rule) {
    validation_rules_[key] = rule;
}

void Config::load_default_validation_rules() {
    // 添加基本的打印机配置验证规则
    // 按照结构体成员声明顺序初始化
    add_validation_rule("printer.kinematics", ConfigValidationRule{
        "string",                              // type
        true,                                  // required
        "",                                    // default_value
        {"cartesian", "corexy", "delta"},      // enum_values
        0.0,                                   // min_value
        0.0,                                   // max_value
        "",                                    // regex_pattern
        "Printer kinematics type"              // description
    });
    
    add_validation_rule("printer.max_velocity", ConfigValidationRule{
        "float",                               // type
        true,                                  // required
        "",                                    // default_value
        {},                                    // enum_values
        0.0,                                   // min_value
        1000.0,                               // max_value
        "",                                    // regex_pattern
        "Maximum velocity in mm/s"             // description
    });
    
    // 添加更多默认验证规则...
}

bool Config::validate() const {
    validation_errors_.clear();
    
    if (config_.empty()) {
        validation_errors_.push_back("Empty config");
        return false;
    }

    bool valid = true;
    
    // 检查所有验证规则
    for (const auto& [key, rule] : validation_rules_) {
        try {
            nlohmann::json::json_pointer ptr("/" + key);
            
            // 检查必需字段
            if (rule.required && !config_.contains(ptr)) {
                validation_errors_.push_back("Missing required field: " + key);
                valid = false;
                continue;
            }
            
            // 如果字段不存在且不是必需的，跳过其他验证
            if (!config_.contains(ptr)) {
                continue;
            }
            
            const auto& value = config_.at(ptr);
            
            // 类型检查
            if (rule.type == "string") {
                if (!value.is_string()) {
                    validation_errors_.push_back("Field " + key + " must be a string");
                    valid = false;
                } else if (!rule.regex_pattern.empty()) {
                    std::regex pattern(rule.regex_pattern);
                    if (!std::regex_match(value.get<std::string>(), pattern)) {
                        validation_errors_.push_back("Field " + key + " does not match pattern: " + rule.regex_pattern);
                        valid = false;
                    }
                }
            } else if (rule.type == "int") {
                if (!value.is_number_integer()) {
                    validation_errors_.push_back("Field " + key + " must be an integer");
                    valid = false;
                }
            } else if (rule.type == "float") {
                if (!value.is_number()) {
                    validation_errors_.push_back("Field " + key + " must be a number");
                    valid = false;
                }
            } else if (rule.type == "bool") {
                if (!value.is_boolean()) {
                    validation_errors_.push_back("Field " + key + " must be a boolean");
                    valid = false;
                }
            }
            
            // 范围检查
            if (value.is_number()) {
                double num_value = value.get<double>();
                if (rule.min_value != rule.max_value) {  // 如果设置了范围
                    if (num_value < rule.min_value || num_value > rule.max_value) {
                        validation_errors_.push_back("Field " + key + " must be between " + 
                            std::to_string(rule.min_value) + " and " + std::to_string(rule.max_value));
                        valid = false;
                    }
                }
            }
            
            // 枚举值检查
            if (!rule.enum_values.empty() && value.is_string()) {
                std::string str_value = value.get<std::string>();
                if (std::find(rule.enum_values.begin(), rule.enum_values.end(), str_value) == rule.enum_values.end()) {
                    validation_errors_.push_back("Field " + key + " must be one of: " + 
                        std::accumulate(std::next(rule.enum_values.begin()), rule.enum_values.end(),
                            rule.enum_values[0], [](std::string a, std::string b) { return a + ", " + b; }));
                    valid = false;
                }
            }
            
        } catch (const std::exception& e) {
            validation_errors_.push_back("Error validating " + key + ": " + e.what());
            valid = false;
        }
    }
    
    return valid;
}

std::vector<std::string> Config::get_validation_errors() const {
    return validation_errors_;
}

bool Config::save() const {
    if (config_path_.empty()) {
        logger_.log(Logger::ERROR, "No config file path available for save");
        return false;
    }

    try {
        // 创建备份文件
        std::string backup_path = config_path_ + ".backup";
        std::ifstream src(config_path_, std::ios::binary);
        if (src) {
            std::ofstream dst(backup_path, std::ios::binary);
            dst << src.rdbuf();
        }

        // 保存新配置
        std::ofstream file(config_path_);
        if (!file.is_open()) {
            logger_.log(Logger::ERROR, "Cannot open config file for writing: " + config_path_);
            return false;
        }

        // 使用4个空格缩进，保持JSON格式美观
        file << config_.dump(4);
        file.close();

        logger_.log(Logger::INFO, "Config saved successfully to: " + config_path_);
        return true;
    } catch (const std::exception& e) {
        logger_.log(Logger::ERROR, "Failed to save config: " + std::string(e.what()));
        return false;
    }
}

bool Config::auto_save() {
    auto_save_enabled_ = true;
    return save();
}

bool Config::reload() {
    if (config_path_.empty()) {
        logger_.log(Logger::ERROR, "No config file path available for reload");
        return false;
    }

    // 如果启用了自动保存，先保存当前配置
    if (auto_save_enabled_) {
        if (!save()) {
            logger_.log(Logger::WARNING, "Failed to auto-save config before reload");
        }
    }

    return parse_file(config_path_);
}

void Config::set_string(const std::string& key, const std::string& value) {
    std::string old_value = get_string(key, "");
    config_[key] = value;
    
    // 触发配置变更事件
    ConfigChangeEvent event{
        key,                                    // key
        old_value,                             // old_value
        value,                                 // new_value
        old_value.empty() ? "add" : "modify"   // change_type
    };
    notify_change(event);
    
    // 如果启用了自动保存，保存配置
    if (auto_save_enabled_) {
        save();
    }
}

void Config::set_int(const std::string& key, int value) {
    std::string old_value = std::to_string(get_int(key, 0));
    config_[key] = value;
    
    ConfigChangeEvent event{
        key,                                    // key
        old_value,                             // old_value
        std::to_string(value),                 // new_value
        old_value == "0" ? "add" : "modify"    // change_type
    };
    notify_change(event);
    
    if (auto_save_enabled_) {
        save();
    }
}

void Config::set_float(const std::string& key, float value) {
    std::string old_value = std::to_string(get_float(key, 0.0f));
    config_[key] = value;
    
    ConfigChangeEvent event{
        key,
        old_value,
        std::to_string(value),
        old_value == "0.000000" ? "add" : "modify"
    };
    notify_change(event);
    
    if (auto_save_enabled_) {
        save();
    }
}

void Config::set_bool(const std::string& key, bool value) {
    std::string old_value = get_bool(key, false) ? "true" : "false";
    config_[key] = value;
    
    ConfigChangeEvent event{
        key,
        old_value,
        value ? "true" : "false",
        old_value == "false" ? "add" : "modify"
    };
    notify_change(event);
    
    if (auto_save_enabled_) {
        save();
    }
}

std::string Config::get_string(const std::string& key, const std::string& default_val) const {
    if (is_deprecated(key)) {
        std::string message = deprecation_messages_.at(key);
        logger_.log(Logger::WARNING, "Using deprecated config key '" + key + "': " + message);
    }

    try {
        nlohmann::json::json_pointer ptr("/" + key);
        if (config_.contains(ptr)) {
            return config_.at(ptr).get<std::string>();
        }
    } catch (...) {
        // 使用默认值
    }
    return default_val;
}

int Config::get_int(const std::string& key, int default_val) const {
    if (is_deprecated(key)) {
        std::string message = deprecation_messages_.at(key);
        logger_.log(Logger::WARNING, "Using deprecated config key '" + key + "': " + message);
    }

    try {
        nlohmann::json::json_pointer ptr("/" + key);
        if (config_.contains(ptr)) {
            return config_.at(ptr).get<int>();
        }
    } catch (...) {
        // 使用默认值
    }
    return default_val;
}

float Config::get_float(const std::string& key, float default_val) const {
    if (is_deprecated(key)) {
        std::string message = deprecation_messages_.at(key);
        logger_.log(Logger::WARNING, "Using deprecated config key '" + key + "': " + message);
    }

    try {
        nlohmann::json::json_pointer ptr("/" + key);
        if (config_.contains(ptr)) {
            return config_.at(ptr).get<float>();
        }
    } catch (...) {
        // 使用默认值
    }
    return default_val;
}

bool Config::get_bool(const std::string& key, bool default_val) const {
    // 检查是否是废弃的配置项
    if (is_deprecated(key)) {
        std::string message = deprecation_messages_.at(key);
        logger_.log(Logger::WARNING, "Using deprecated config key '" + key + "': " + message);
    }

    try {
        nlohmann::json::json_pointer ptr("/" + key);
        if (config_.contains(ptr)) {
            return config_.at(ptr).get<bool>();
        }
    } catch (...) {
        // 使用默认值
    }
    return default_val;
}

void Config::mark_deprecated(const std::string& key, const std::string& message) {
    deprecated_keys_.insert(key);
    if (!message.empty()) {
        deprecation_messages_[key] = message;
    } else {
        deprecation_messages_[key] = "This configuration option is deprecated and will be removed in a future version.";
    }
}

bool Config::is_deprecated(const std::string& key) const {
    return deprecated_keys_.find(key) != deprecated_keys_.end();
}

std::map<std::string, std::string> Config::get_deprecated_items() const {
    std::map<std::string, std::string> items;
    for (const auto& key : deprecated_keys_) {
        if (config_.contains(key)) {
            items[key] = deprecation_messages_.at(key);
        }
    }
    return items;
}

void Config::add_change_listener(const ConfigChangeCallback& callback) {
    change_listeners_.push_back(callback);
}

void Config::remove_change_listener(const ConfigChangeCallback& callback) {
    // 由于std::function不能直接比较，我们需要创建一个新的vector并保留不匹配的回调
    std::vector<ConfigChangeCallback> new_listeners;
    new_listeners.reserve(change_listeners_.size());
    
    // 这里我们通过比较函数指针的地址来移除特定的监听器
    // 注意：这种方法可能不是100%可靠，但对于大多数用例来说足够了
    for (const auto& listener : change_listeners_) {
        if (listener.target_type() != callback.target_type()) {
            new_listeners.push_back(listener);
        }
    }
    
    change_listeners_ = std::move(new_listeners);
}

void Config::notify_change(const ConfigChangeEvent& event) {
    for (const auto& listener : change_listeners_) {
        try {
            listener(event);
        } catch (const std::exception& e) {
            logger_.log(Logger::ERROR, "Error in config change listener: " + std::string(e.what()));
        }
    }
}

bool Config::has_key(const std::string& key) const {
    try {
        nlohmann::json::json_pointer ptr("/" + key);
        return config_.contains(ptr);
    } catch (...) {
        return false;
    }
}

std::vector<std::string> Config::get_keys() const {
    std::vector<std::string> keys;
    for (auto it = config_.begin(); it != config_.end(); ++it) {
        keys.push_back(it.key());
    }
    return keys;
}

std::string Config::get_description(const std::string& key) const {
    auto it = validation_rules_.find(key);
    if (it != validation_rules_.end()) {
        return it->second.description;
    }
    return "";
}